package com.turing.post.cardtransactions.impl;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.ejb.EJB;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;

import com.turing.post.account.util.AccountBusiness;
import com.turing.post.account.util.MasterAccount;
import com.turing.post.account.util.MasterAccountDao;
import com.turing.post.account.util.OpenAccountParam;
import com.turing.post.account.util.OpenAccountResult;
import com.turing.post.account.util.SalesGroup;
import com.turing.post.account.util.SubAccount;
import com.turing.post.account.util.SubAccountDao;
import com.turing.post.account.util.OpenAccountResult.OpenAccountResult_;
import com.turing.post.capitalaccounts.util.SaleCapitalDetail;
import com.turing.post.capitalaccounts.util.SaleCapitalDetailDao;
import com.turing.post.cardmanagement.util.ActivateCard;
import com.turing.post.cardmanagement.util.ActivateCardDao;
import com.turing.post.cardmanagement.util.CardClassic;
import com.turing.post.cardmanagement.util.CardClassicDao;
import com.turing.post.cardmanagement.util.CardStock;
import com.turing.post.cardmanagement.util.CardStockDao;
import com.turing.post.cardmanagement.util.MakeCardControl;
import com.turing.post.cardmanagement.util.MakeCardControlDao;
import com.turing.post.cardmanagement.util.NonEntityCard;
import com.turing.post.cardtransactions.util.CardTranApplicationException;
import com.turing.post.cardtransactions.util.SaleTransBusiness;
import com.turing.post.common.util.PCPSCommonDao;
import com.turing.post.common.util.SysOpUser;
import com.turing.post.common.util.SysOpUserDao;
import com.turing.post.common.util.SysOperLog;
import com.turing.post.common.util.SysOperLogDao;
import com.turing.post.organization.util.CreditAccDetail;
import com.turing.post.organization.util.IssueBranchBusiness;
import com.turing.post.organization.util.IssueCompany;
import com.turing.post.organization.util.IssueCompanyDao;
import com.turing.post.organization.util.SaleBranch;
import com.turing.post.organization.util.SaleBranchDao;
import com.turing.post.organization.util.SysBranch;
import com.turing.post.organization.util.SysBranchDao;
import com.turing.post.salesmanage.util.SaleOrder;
import com.turing.post.salesmanage.util.SaleOrderActionDetail;
import com.turing.post.salesmanage.util.SaleOrderActionDetailDao;
import com.turing.post.salesmanage.util.SaleOrderCardDetail;
import com.turing.post.salesmanage.util.SaleOrderCardDetailDao;
import com.turing.post.salesmanage.util.SaleOrderDao;
import com.turing.post.salesmanage.util.SaleOrderPaidDetail;
import com.turing.post.salesmanage.util.SaleOrderPaidDetailDao;
import com.turing.post.salesmanage.util.SaleOrderRealNameDetail;
import com.turing.post.salesmanage.util.SaleOrderRealNameDetailDao;
import com.turing.post.salesmanage.util.SaleOrderSalesDetail;
import com.turing.post.salesmanage.util.SaleOrderSalesDetailDao;
import com.turing.post.util.PCPSApplicationException;
import com.turing.post.util.PCPSUtil;
import com.turing.post.util.PCPSWebInput;
import com.turing.post.util.SHA1;

@Stateless(mappedName = "cardtransactions.impl.SaleTransBusinessImpl")
@Remote
@Local
public class SaleTransBusinessImpl implements SaleTransBusiness {

	@EJB(mappedName = "common.impl.PCPSCommonDaoImpl")
	private PCPSCommonDao pcpsCommonDaoImpl;

	@EJB(mappedName = "salesmanage.impl.SaleOrderDaoImpl")
	private SaleOrderDao saleOrderDaoImpl;

	@EJB(mappedName = "common.impl.SysOpUserDaoImpl")
	private SysOpUserDao sysOpUserDaoImpl;

	@EJB(mappedName = "organization.impl.SysBranchDaoImpl")
	private SysBranchDao sysBranchDaoImpl;

	@EJB(mappedName = "organization.impl.IssueCompanyDaoImpl")
	private IssueCompanyDao issueCompanyDaoImpl;

	@EJB(mappedName = "organization.impl.SaleBranchDaoImpl")
	private SaleBranchDao saleBranchDaoImpl;

	@EJB(mappedName = "salesmanage.impl.SaleOrderCardDetailDaoImpl")
	private SaleOrderCardDetailDao saleOrderCardDetailDaoImpl;

	@EJB(mappedName = "cardmanagement.impl.CardStockDaoImpl")
	private CardStockDao cardStockDaoImpl;

	@EJB(mappedName = "salesmanage.impl.SaleOrderRealNameDetailDaoImpl")
	private SaleOrderRealNameDetailDao saleOrderRealNameDetailDaoImpl;

	@EJB(mappedName = "salesmanage.impl.SaleOrderSalesDetailDaoImpl")
	private SaleOrderSalesDetailDao saleOrderSalesDetailDaoImpl;

	@EJB(mappedName = "salesmanage.impl.SaleOrderPaidDetailDaoImpl")
	private SaleOrderPaidDetailDao saleOrderPaidDetailDaoImpl;

	@EJB(mappedName = "account.impl.AccountBusinessImpl")
	private AccountBusiness accountBusinessImpl;

	@EJB(mappedName = "salesmanage.impl.SaleOrderActionDetailDaoImpl")
	private SaleOrderActionDetailDao saleOrderActionDetailDaoImpl;

	@EJB(mappedName = "cardmanagement.impl.ActivateCardDaoImpl")
	private ActivateCardDao activateCardDaoImpl;

	@EJB(mappedName = "cardmanagement.impl.MakeCardControlDaoImpl")
	private MakeCardControlDao makeCardControlDaoImpl;

	@EJB(mappedName = "common.impl.SysOperLogDaoImpl")
	private SysOperLogDao sysOperLogDaoImpl;
	@EJB(mappedName = "capitalaccounts.impl.SaleCapitalDetailDaoImpl")
	private SaleCapitalDetailDao saleCapitalDetailDaoImpl;

	@EJB(mappedName = "cardmanagement.impl.CardClassicDaoImpl")
	private CardClassicDao cardClassicDaoImpl;

	@EJB(mappedName = "organization.impl.IssueBranchBusinessImpl")
	private IssueBranchBusiness issueBranchBusinessImpl;

	/**
	 * 返回有效的购卡人信息
	 * 
	 * @param saleOrder
	 * @return
	 */
	private BigInteger getRealBuyerId(SaleOrder saleOrder) {
		if (saleOrder == null)
			return null;

		if (PCPSUtil.compareObject(saleOrder.getBuyerType(),
				SaleOrder.SaleOrder_BuyerType_Person))
			return saleOrder.getPersonalBuyerId();

		return saleOrder.getOrganizeBuyerId();
	}

	/**
	 * 获取有效的激活单
	 * 
	 * @param activeOrderId
	 * @return
	 * @throws PCPSApplicationException
	 */
	// private ActiveOrder getValidActiveOrderByActiveOrderId(
	// BigInteger activeOrderId) throws PCPSApplicationException {
	//
	// ActiveOrder activeOrder = activeOrderDaoImpl
	// .lockActiveOrder(activeOrderId);
	// if (activeOrder == null)
	// throw new CardTranApplicationException(
	// CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
	// "", "无效的激活单ID" + activeOrderId);
	//
	// return activeOrder;
	// }
	/**
	 * 获取有效的销售单
	 * 
	 * @param saleOrderId
	 * @return
	 * @throws PCPSApplicationException
	 */
	private SaleOrder getValidSaleOrderBySaleOrderId(BigInteger saleOrderId)
			throws PCPSApplicationException {
		SaleOrder saleOrder = saleOrderDaoImpl
				.getSaleOrderBySaleOrderId(saleOrderId);
		if (saleOrder == null)
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "无效的销售单ID" + saleOrderId);
		return saleOrder;
	}

	/**
	 * 根据操作员ID获取有效的发卡商
	 * 
	 * @param operId
	 * @return
	 * @throws PCPSApplicationException
	 */
	private IssueCompany getValidIssueCompanyByOperId(BigInteger operId)
			throws PCPSApplicationException {

		// 先查询操作员ID
		SysOpUser sou = sysOpUserDaoImpl.getSysOpUserByOperId(operId);
		if (sou == null || PCPSUtil.isEmpty(sou.getOperBranchNo()))
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "无效的操作员ID" + operId);

		// 再查询系统机构
		SysBranch sb = sysBranchDaoImpl.getSysBranchByBranchNo(sou
				.getOperBranchNo());

		if (sb == null
				|| !(PCPSUtil.compareObject(sb.getBranchType(),
						SysBranch.SYSBRANCH_ISSUECOMPANY) || PCPSUtil
						.compareObject(sb.getBranchType(),
								SysBranch.SYSBRANCH_ISSUEBRANCH)))
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "无效的操作员ID[" + operId.toString()
							+ "]或权限[必须是发卡商或发卡商机构人员]");

		IssueCompany issueCompany = issueCompanyDaoImpl
				.getIssueCompanyByIssueCompanyNo(sb.getBranchNo().substring(0,
						6));
		if (issueCompany == null)
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "无效的发卡商" + sb.getBranchNo());

		// 检查发卡商权限

		return issueCompany;
	}

	/**
	 * 获取有效的销售机构号
	 * 
	 * @param saleBranchNo
	 * @return
	 * @throws PCPSApplicationException
	 */
	private SaleBranch getValidSaleBranchBySaleBranchNo(String saleBranchNo)
			throws PCPSApplicationException {
		SaleBranch saleBranch = saleBranchDaoImpl
				.getSaleBranchBySaleBranchNo(saleBranchNo);
		if (saleBranch == null)
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "无效的销售机构号" + saleBranchNo);

		return saleBranch;
	}

	// /**
	// * 根据销售机构号查找销售商
	// *
	// * @param saleBranch
	// * @return
	// * @throws PCPSApplicationException
	// */
	// private SaleCompany getValidSaleCompanyBySaleBranchNo(SaleBranch
	// saleBranch)
	// throws PCPSApplicationException {
	// SaleCompany saleCompany = null;
	// /**
	// * 1.判断销售商号是否存在,若不存在,则取此销售机构上级机构的销售商信息
	// */
	// if (saleBranch.getSaleCompanyNo() == null) {
	// String saleBrchNo = saleBranch.getSaleBranchNo();
	// SaleBranch superSb = null;
	// while (true) {
	// superSb = saleBranchDaoImpl
	// .getSaleBranchBySaleBranchNo(saleBrchNo);
	// if (superSb.getSaleCompanyNo() == null) {
	// saleBrchNo = superSb.getSuperSaleBranchNo();
	// continue;
	// }
	// saleCompany = saleCompanyDaoImpl
	// .getSaleCompanyBySaleCompanyNo(superSb
	// .getSaleCompanyNo());
	// break;
	// }
	// if (saleCompany == null)
	// throw new CardTranApplicationException(
	// CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
	// "", "无效的销售商号" + saleBranch.getSaleCompanyNo());
	// return saleCompany;
	// }
	// /**
	// * 2.如果此销售机构存在销售商号,则返回销售商信息
	// */
	// saleCompany = saleCompanyDaoImpl
	// .getSaleCompanyBySaleCompanyNo(saleBranch.getSaleCompanyNo());
	// if (saleCompany == null)
	// throw new CardTranApplicationException(
	// CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
	// "", "无效的销售商号" + saleBranch.getSaleCompanyNo());
	//
	// return saleCompany;
	// }

	/**
	 * 获得有效的销售员信息
	 * 
	 * @param saleOrder
	 * @return
	 * @throws PCPSApplicationException
	 */
	private ArrayList<SalesGroup> getValidSalesBySaleOrder(SaleOrder saleOrder)
			throws PCPSApplicationException {

		ArrayList<SalesGroup> sglist = new ArrayList<SalesGroup>();

		List<SaleOrderSalesDetail> sosdlist = saleOrderSalesDetailDaoImpl
				.getSaleOrderSalesDetailListBySaleOrderId(saleOrder
						.getSaleOrderId());

		if (sosdlist == null || sosdlist.size() < 1)
			return null;

		Integer degree = 0;
		for (SaleOrderSalesDetail sosd : sosdlist) {
			SalesGroup sg = new SalesGroup();
			sg.setSalesGroupId(null);
			sg.setSalesId(sosd.getSalesId());
			BigDecimal bd = new BigDecimal(sosd.getSalesAmount())
					.divide(new BigDecimal(saleOrder.getTotalSaleAmount()));
			sg.setDegreeOfcontribution(bd.toBigInteger());
			sglist.add(sg);
			degree += bd.toBigInteger().intValue();
		}

		if (degree > 101 || degree < 0)
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "销售单" + saleOrder.getSaleOrderId().toString()
							+ "销售员业绩贡献度无效!");

		return sglist;
	}

	/**
	 * 异常抛出
	 * 
	 * @param issueCompany
	 * @throws PCPSApplicationException
	 */
	private void invalidIssueCompany(String issueCompanyNo)
			throws PCPSApplicationException {
		throw new CardTranApplicationException(
				CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
				"无效的发卡商号" + (issueCompanyNo == null ? null : issueCompanyNo));
	}

	/**
	 * 获取完整的售卡列表
	 * 
	 * @param saleOrder
	 * @param cardamtmap
	 * @param cardclassicmap
	 * @return
	 * @throws PCPSApplicationException
	 */
	private Map<String, CardStock> getAllCardOfSaleOrder(SaleOrder saleOrder,
			Map<String, BigInteger> cardamtmap,
			Map<String, BigInteger> cardclassicmap)
			throws PCPSApplicationException {

		Map<String, CardStock> allcard = new HashMap<String, CardStock>();

		List<SaleOrderCardDetail> socdlist = saleOrderCardDetailDaoImpl
				.getSaleOrderCardDetailListBySaleOrderId(saleOrder
						.getSaleOrderId());

		if (socdlist == null || socdlist.size() < 1)
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "销售单" + saleOrder.getSaleOrderId().toString()
							+ "无有效的售卡记录!");

		BigInteger factsaleamt = BigInteger.ZERO;

		// 循环处理售卡明细
		for (SaleOrderCardDetail socd : socdlist) {
			// 序号张数 -- (终止序号 - 起始序号 + 1)
			BigInteger factcount = new BigInteger(socd.getEndCardSeqNo())
					.subtract(new BigInteger(socd.getStartCardSeqNo())).add(
							BigInteger.ONE);
			// 实际的卡张数 -- 从5个参数改为4个参数,去掉状态检测
			List<CardStock> cslist = cardStockDaoImpl
					.getCardStockListByFilterForUpdate(socd.getBatchNo(),
							saleOrder.getSaleBranchNo(), socd
									.getStartCardSeqNo(), socd
									.getEndCardSeqNo());

			// 检查张数
			if (cslist == null || socd.getCardCount() < 1
					|| socd.getCardCount() != cslist.size())
				throw new CardTranApplicationException(
						CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "销售单" + saleOrder.getSaleOrderSeqNo() + "售卡序号"
								+ socd.getStartCardSeqNo() + "有问题!");

			BigInteger amt = new BigInteger(socd.getInitDeposit().toString());
			BigInteger cardcount = new BigInteger(socd.getCardCount()
					.toString());

			// 再次检查张数
			if (cardcount.compareTo(factcount) != 0)
				throw new CardTranApplicationException(
						CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "销售单" + saleOrder.getSaleOrderSeqNo() + "售卡序号"
								+ socd.getStartCardSeqNo() + "卡张数有问题,"
								+ cardcount.toString() + "<>"
								+ factcount.toString() + "!");

			// 检查金额
			if (amt.compareTo(BigInteger.ZERO) < 0
					|| socd.getOrderLineTotal().compareTo(
							amt.multiply(cardcount)) != 0)
				throw new CardTranApplicationException(
						CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "销售单" + saleOrder.getSaleOrderId().toString()
								+ "售卡金额非法!");

			// 计算累计销售额
			factsaleamt = factsaleamt.add(socd.getOrderLineTotal());

			// 循环处理售卡明细
			for (CardStock cs : cslist) {
				// 检查状态 -- 必须是等待激活或者激活取消待重新入库
				if (!(PCPSUtil
						.compareObject(CardStock.CARDSTOCK_STATUS_WAITACTIVATE,
								cs.getStatus()) || PCPSUtil.compareObject(
						CardStock.CARDSTOCK_STATUS_ACTIVATECANCEL, cs
								.getStatus())))
					throw new CardTranApplicationException(
							CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
							"", "销售单" + saleOrder.getSaleOrderSeqNo() + "售卡卡序号"
									+ cs.getCardSeqNo() + "库存状态有问题!");
				if (allcard.containsKey(cs.getCardNo()))
					throw new CardTranApplicationException(
							CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
							"", "销售单" + saleOrder.getSaleOrderId().toString()
									+ "售卡卡序号" + cs.getCardSeqNo() + "可能重复!");
				allcard.put(cs.getCardNo(), cs);
				// 卡号与销售金额映射关系
				cardamtmap.put(cs.getCardNo(), new BigInteger(socd
						.getInitDeposit().toString()));
				// 卡号与卡种类映射关系
				cardclassicmap.put(cs.getCardNo(), socd.getCardClassicId());
			}
		}

		// 比较销售额
		if (factsaleamt.compareTo(saleOrder.getTotalSaleAmount()) != 0)
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "销售单" + saleOrder.getSaleOrderId().toString()
							+ "售卡金额非法!");

		if (allcard.size() != saleOrder.getTotalCardCount())
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "销售单" + saleOrder.getSaleOrderId().toString()
							+ "售卡总张数错!");

		return allcard;
	}

	/**
	 * 获取完整的售卡列表
	 * 
	 * @param saleOrder
	 * @param cardamtmap
	 * @param cardclassicmap
	 * @return
	 * @throws PCPSApplicationException
	 */
	private Map<String, CardStock> getAppManageCardOfSaleOrder(
			SaleOrder saleOrder, Map<String, BigInteger> cardamtmap,
			Map<String, BigInteger> cardclassicmap)
			throws PCPSApplicationException {

		Map<String, CardStock> allcard = new HashMap<String, CardStock>();

		List<SaleOrderCardDetail> socdlist = saleOrderCardDetailDaoImpl
				.getSaleOrderCardDetailListBySaleOrderId(saleOrder
						.getSaleOrderId());

		if (socdlist == null || socdlist.size() < 1)
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "销售单" + saleOrder.getSaleOrderId().toString()
							+ "无有效的售卡记录!");

		BigInteger factsaleamt = BigInteger.ZERO;

		// 循环处理售卡明细
		for (SaleOrderCardDetail socd : socdlist) {
			// 序号张数 -- (终止序号 - 起始序号 + 1)
			BigInteger factcount = new BigInteger(socd.getEndCardSeqNo())
					.subtract(new BigInteger(socd.getStartCardSeqNo())).add(
							BigInteger.ONE);
			// 实际的卡张数 -- 从5个参数改为4个参数,去掉状态检测
			List<CardStock> cslist = cardStockDaoImpl
					.getCardStockListByFilterForUpdate(socd.getBatchNo(),
							saleOrder.getSaleBranchNo(), socd
									.getStartCardSeqNo(), socd
									.getEndCardSeqNo());

			// 检查张数
			if (cslist == null || socd.getCardCount() < 1
					|| socd.getCardCount() != cslist.size())
				throw new CardTranApplicationException(
						CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "销售单" + saleOrder.getSaleOrderSeqNo() + "售卡序号"
								+ socd.getStartCardSeqNo() + "有问题!");

			BigInteger amt = new BigInteger(socd.getInitDeposit().toString());
			BigInteger cardcount = new BigInteger(socd.getCardCount()
					.toString());

			// 再次检查张数
			if (cardcount.compareTo(factcount) != 0)
				throw new CardTranApplicationException(
						CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "销售单" + saleOrder.getSaleOrderSeqNo() + "售卡序号"
								+ socd.getStartCardSeqNo() + "卡张数有问题,"
								+ cardcount.toString() + "<>"
								+ factcount.toString() + "!");

			// 检查金额
			if (amt.compareTo(BigInteger.ZERO) < 0
					|| socd.getOrderLineTotal().compareTo(
							amt.multiply(cardcount)) != 0)
				throw new CardTranApplicationException(
						CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "销售单" + saleOrder.getSaleOrderId().toString()
								+ "售卡金额非法!");

			// 计算累计销售额
			factsaleamt = factsaleamt.add(socd.getOrderLineTotal());

			// 循环处理售卡明细
			for (CardStock cs : cslist) {
				// 检查状态 -- 必须是等待激活或者激活取消待重新入库
				if (!(PCPSUtil.compareObject(CardStock.CARDSTOCK_STATUS_NORMAL,
						cs.getStatus())))
					throw new CardTranApplicationException(
							CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
							"", "销售单" + saleOrder.getSaleOrderSeqNo() + "售卡卡序号"
									+ cs.getCardSeqNo() + "库存状态有问题!");
				if (allcard.containsKey(cs.getCardNo()))
					throw new CardTranApplicationException(
							CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
							"", "销售单" + saleOrder.getSaleOrderId().toString()
									+ "售卡卡序号" + cs.getCardSeqNo() + "可能重复!");
				allcard.put(cs.getCardNo(), cs);
				// 卡号与销售金额映射关系
				cardamtmap.put(cs.getCardNo(), new BigInteger(socd
						.getInitDeposit().toString()));
				// 卡号与卡种类映射关系
				cardclassicmap.put(cs.getCardNo(), socd.getCardClassicId());
			}
		}

		// 比较销售额
		if (factsaleamt.compareTo(saleOrder.getTotalSaleAmount()) != 0)
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "销售单" + saleOrder.getSaleOrderId().toString()
							+ "售卡金额非法!");

		if (allcard.size() != saleOrder.getTotalCardCount())
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "销售单" + saleOrder.getSaleOrderId().toString()
							+ "售卡总张数错!");

		return allcard;
	}

	/**
	 * 获取销售单实名持卡人信息
	 * 
	 * @param saleOrder
	 * @return
	 * @throws PCPSApplicationException
	 */
	private Map<String, BigInteger> getAllCardOwnerOfSaleOrder(
			SaleOrder saleOrder) throws PCPSApplicationException {
		Map<String, BigInteger> owner = new HashMap<String, BigInteger>();

		List<SaleOrderRealNameDetail> sorndlist = saleOrderRealNameDetailDaoImpl
				.getAllSaleOrderRealNameDetailList(saleOrder.getSaleOrderId());

		for (SaleOrderRealNameDetail sornd : sorndlist) {
			if (owner.containsKey(sornd.getCardNo()))
				throw new CardTranApplicationException(
						CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "销售单号" + saleOrder.getSaleOrderId() + "实名持卡人卡号"
								+ sornd.getCardNo() + "重复!");
			owner.put(sornd.getCardNo(), sornd.getCustomId());
		}

		return owner;
	}

	/**
	 * 生成所有开户的卡信息
	 * 
	 * @param saleOrder
	 * @param allcard
	 * @param allcardowner
	 * @return
	 * @throws PCPSApplicationException
	 */
	ArrayList<OpenAccountParam> generateAllOpenAccountCards(
			SaleOrder saleOrder, Map<String, CardStock> allcard,
			Map<String, BigInteger> allcardowner,
			Map<String, BigInteger> allcardamt) throws PCPSApplicationException {
		ArrayList<OpenAccountParam> oapl = new ArrayList<OpenAccountParam>();

		for (Map.Entry<String, CardStock> cs : allcard.entrySet()) {
			OpenAccountParam oap = new OpenAccountParam();
			oap.cardNo = cs.getKey();
			oap.initialAmount = allcardamt.get(cs.getKey());
			if (!allcardowner.containsKey(cs.getKey()))
				oap.ownerId = null;
			else
				oap.ownerId = allcardowner.get(cs.getKey());
			oapl.add(oap);
		}
		return oapl;
	}

	/**
	 * 生成所有开户的卡信息
	 * 
	 * @param saleOrder
	 * @param allcard
	 * @param allcardowner
	 * @return
	 * @throws PCPSApplicationException
	 */
	ArrayList<OpenAccountParam> generateAppManageOpenAccountCards(
			SaleOrder saleOrder, Map<String, CardStock> allcard,
			Map<String, BigInteger> allcardowner,
			Map<String, BigInteger> allcardamt) throws PCPSApplicationException {
		ArrayList<OpenAccountParam> oapl = new ArrayList<OpenAccountParam>();

		for (Map.Entry<String, CardStock> cs : allcard.entrySet()) {
			OpenAccountParam oap = new OpenAccountParam();
			oap.cardNo = cs.getKey();
			oap.initialAmount = allcardamt.get(cs.getKey());
			if (!allcardowner.containsKey(cs.getKey()))
				oap.ownerId = null;
			else
				oap.ownerId = allcardowner.get(cs.getKey());
			oapl.add(oap);

			OpenAccountParam oap1 = new OpenAccountParam();
			oap1.cardNo = cs.getKey();
			oap1.initialAmount = allcardamt.get(cs.getKey());
			if (!allcardowner.containsKey(cs.getKey()))
				oap1.ownerId = null;
			else
				oap1.ownerId = allcardowner.get(cs.getKey());
			oapl.add(oap1);
		}
		return oapl;
	}

	/**
	 * 检查是否可以激活
	 * 
	 * @param issueCompany
	 * @param saleOrder
	 * @param saleCompany
	 * @param saleBranch
	 * @throws PCPSApplicationException
	 */
	private void canActivateSaleOrder(IssueCompany issueCompany,
			SaleOrder saleOrder, SaleBranch saleBranch)
			throws PCPSApplicationException {

		// 检查销售单状态
		if (!PCPSUtil.compareObject(saleOrder.getOrderStatus(),
				SaleOrder.SaleOrder_OrderStatus_AuthCard))
			throw new CardTranApplicationException("", "销售单号"
					+ saleOrder.getSaleOrderId() + "状态无效!");

		// 必须填写了激活机构号
		if (PCPSUtil.isEmpty(saleOrder.getActivateBranchNo()))
			throw new CardTranApplicationException("", "销售单号"
					+ saleOrder.getSaleOrderId() + "尚未提交激活请求!");

		String issueCompanyNo = issueCompany.getIssueCompanyNo();

		// 必须与issueCompany一致
		if (!PCPSUtil.compareObject(issueCompanyNo, PCPSUtil
				.getICNoByBranchNo(saleBranch.getIssueBranchNo())))
			invalidIssueCompany(issueCompanyNo);

		// // 检查销售机构信用度
		// BigInteger balance = saleBranch.getCredit();
		// balance = balance.subtract(saleOrder.getTotalSaleAmount());
		// if (balance.compareTo(saleBranch.getCreditLowLimit()) < 0)
		// throw new CardTranApplicationException(
		// CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
		// "", "销售机构" + saleBranch.getSaleBranchNo() + "信用度不足!");
	}

	/**
	 * 从卡库存表中真正删除
	 * 
	 * @param csmap
	 * @throws PCPSApplicationException
	 */
	private void removeAllActivateCard(Map<String, CardStock> csmap)
			throws PCPSApplicationException {
		for (Map.Entry<String, CardStock> cs : csmap.entrySet()) {
			CardStock dbcs = cardStockDaoImpl.getCardStockByCardseqno(cs
					.getValue().getCardSeqNo());
			if (dbcs != null)
				cardStockDaoImpl.removeCardStock(dbcs);
		}
	}

	/**
	 * 根据销售单号从卡库存表中真正删除
	 * 
	 * @param csmap
	 * @throws PCPSApplicationException
	 */
	private void removeAllActivateCard(BigInteger saleorderid)
			throws PCPSApplicationException {
		// 获取卡号段信息集合
		List<SaleOrderCardDetail> soclist = saleOrderCardDetailDaoImpl
				.getSaleOrderCardDetailListBySaleOrderId(saleorderid);
		// 根据获取的卡号段信息删除库存表中的数据
		for (SaleOrderCardDetail s : soclist) {
			cardStockDaoImpl.deleteCardStock(s.getBatchNo(), s
					.getStartCardSeqNo(), s.getEndCardSeqNo());
		}
	}

	/**
	 * 按照制卡控制表中批次号的有效期算法,计算有效期
	 * 
	 * @param batchno
	 * @param mccmap
	 * @throws PCPSApplicationException
	 */
	private void calcExpiredByBatchNo(String batchno, Date openTime,
			Map<String, Date> mccmap) throws PCPSApplicationException {
		MakeCardControl makeCardControl = makeCardControlDaoImpl
				.getMakeCardControlByBatchNo(batchno);
		if (makeCardControl == null)
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "制卡批次" + batchno + "不存在!");
		// 计算真正的有效期 -- 需要前台提示,第2个参数
		mccmap.put(batchno, makeCardControl.calcExpired(openTime, openTime));
	}

	/**
	 * 计算激活卡MAC
	 * 
	 * @param saleOrderId
	 * @param cardNo
	 * @param balance
	 * @param expired
	 * @param cardPwd
	 * @return
	 */
	private String getActivateCardMac(BigInteger saleOrderId, String cardNo,
			BigInteger balance, Date expired, String cardPwd) {
		String macsrc = saleOrderId.toString() + cardNo + balance.toString()
				+ (expired == null ? "" : expired.toString()) + cardPwd;
		return new SHA1().getDigestOfString(macsrc.getBytes());
	}

	/**
	 * 产生ActivateCard记录
	 * 
	 * @param csmap
	 * @throws PCPSApplicationException
	 */
	private Map<String, ActivateCard> generateActivateCard(Date openTime,
			SaleOrder saleOrder, Map<String, CardStock> csmap,
			Map<String, BigInteger> allcardowner,
			Map<String, BigInteger> allcardamt,
			Map<String, BigInteger> allcardclassic)
			throws PCPSApplicationException {

		Map<String, ActivateCard> acmap = new HashMap<String, ActivateCard>();
		// 按批次号计算有效期
		Map<String, Date> mccmap = new HashMap<String, Date>();
		// 卡种类MAP
		Map<BigInteger, CardClassic> allcardclassicmap = new HashMap<BigInteger, CardClassic>();

		// 批次号-->CardFaceId
		Map<String, BigInteger> batch_cardfaceid = new HashMap<String, BigInteger>();
		for (Map.Entry<String, CardStock> css : csmap.entrySet()) {
			ActivateCard ac = new ActivateCard();
			CardStock cs = css.getValue();
			CardClassic curccs = null;
			BigInteger curcardfaceid = null;

			// 如果当前未定义批次号与卡种类ID的映射
			if (!batch_cardfaceid.containsKey(cs.getBatchNo())) {
				MakeCardControl mcc = makeCardControlDaoImpl
						.getMakeCardControlByBatchNo(cs.getBatchNo());
				if (mcc == null)
					throw new PCPSApplicationException("", "无效的批次号"
							+ cs.getBatchNo() + "!");
				batch_cardfaceid.put(cs.getBatchNo(), mcc.getCardFaceId());
			}

			curcardfaceid = batch_cardfaceid.get(cs.getBatchNo());

			BigInteger cardclassicid = allcardclassic.get(cs.getCardNo());
			if (cardclassicid == null)
				throw new PCPSApplicationException("", "无效的卡种类"
						+ cs.getCardNo() + "!");

			if (!allcardclassicmap.containsKey(cardclassicid)) {
				CardClassic ccs = cardClassicDaoImpl
						.getCardClassicByCardClassicId(cardclassicid);
				if (ccs == null)
					throw new PCPSApplicationException("", "无效的卡种类ID"
							+ cardclassicid.toString() + "!");
				allcardclassicmap.put(cardclassicid, ccs);
			}

			curccs = allcardclassicmap.get(cardclassicid);
			if (curccs == null)
				throw new PCPSApplicationException("", "无效的卡种类"
						+ cs.getCardNo() + "!");

			BigInteger amt = allcardamt.get(cs.getCardNo());
			String batchno = cs.getBatchNo();
			BigInteger ownerid = allcardowner.get(cs.getCardNo());
			// PCPSUtil.Log("cs.getCardNo()=========="+cs.getCardNo()+"ownerid========="+ownerid);
			// 实名种类卡ownerid必须不为NULL
			if (PCPSUtil.compareObject(curccs.getIsRealName(),
					CardClassic.CARDCLASSIC_STATUS_REALNAME)
					&& ownerid == null)
				throw new PCPSApplicationException("", "", "批次号:"
						+ cs.getBatchNo() + " 卡序号:" + cs.getCardSeqNo()
						+ "是实名卡,但未提供持卡人信息!");

			if (!mccmap.containsKey(batchno))
				calcExpiredByBatchNo(batchno, openTime, mccmap);
			// 实名持卡人将无有效期限制 -- 业务需求
			Date expired = (ownerid != null) ? null : mccmap.get(batchno);
			ac.setBatchNo(batchno);
			ac.setOpenBranchNo(saleOrder.getOpenBranchNo());
			ac.setCardSeqNo(cs.getCardSeqNo());
			ac.setCardNo(cs.getCardNo());
			ac.setCardFaceId(curcardfaceid);
			ac.setCardClassicId(curccs.getCardClassicId());
			ac.setMasterAccNo(null); // 先置为null,开户成功后再置为真正的主帐号
			ac.setWalletAccNo(null);// 钱包账户
			ac.setWalletBalance(BigInteger.ZERO);// 钱包余额
			ac.setCardPwd(cs.getCardPwd());
			ac.setTwoTrackContent(cs.getTwoTrackContent());
			ac.setThirdTrackContent(cs.getThirdTrackContent());
			ac.setSaleBranchNo(saleOrder.getSaleBranchNo());
			ac.setSaleOrderId(saleOrder.getSaleOrderId());
			ac.setBuyerId(getRealBuyerId(saleOrder));
			ac.setOwnerId(ownerid);
			ac.setInitialBalance(amt);
			// 销售时不计开户金额到累计充值字段
			ac.setTotalDeposit(BigInteger.ZERO);
			ac.setBalance(amt);
			ac.setExpired(expired);
			ac.setPwdErrCnt(0);
			ac.setLastPwdErrTime(null);
			ac.setOpenTime(openTime);
			ac.setOpenStatus(ActivateCard.ACTIVATECARD_OPENSTATUS_NORMAL);
			ac.setCloseStatus(ActivateCard.ACTIVATECARD_CLOSESTATUS_NORMAL);
			ac.setLastLossTime(null);
			ac.setLossStatus(ActivateCard.ACTIVATECARD_LOSSSTATUS_NORMAL);
			ac
					.setManualLockStatus(ActivateCard.ACTIVATECARD_MANUALLOCKSTATUS_UNLOCK);

			// 计算卡激活MAC
			String activateMac = getActivateCardMac(saleOrder.getSaleOrderId(),
					ac.getCardNo(), ac.getBalance(), expired, ac.getCardPwd());
			ac.setActivateMac(activateMac);

			// 累计消费次数
			ac.setTotalConsumeCount(BigInteger.ZERO);

			// 插入到激活卡列表
			activateCardDaoImpl.insert(ac);

			// 加入到返回map
			acmap.put(ac.getCardNo(), ac);
		}

		return acmap;
	}

	// /**
	// * 处理激活单状态
	// *
	// * @param activeOrder
	// * @param amt
	// * @param acttime
	// * @throws PCPSApplicationException
	// */
	// @SuppressWarnings("unused")
	// private void handleActivateOrder(ActiveOrder activeOrder, BigInteger amt,
	// Date acttime) throws PCPSApplicationException {
	// BigInteger actamt = activeOrder.getTotalActiveSaleOrderAmount()
	// .add(amt);
	// int cnt = amt.compareTo(BigInteger.ZERO) < 0 ? -1 : 1;
	// activeOrder.setLastActionTime(acttime);
	// activeOrder.setTotalActiveSaleOrderCount(activeOrder
	// .getTotalActiveSaleOrderCount()
	// + cnt);
	// activeOrder.setTotalActiveSaleOrderAmount(actamt);
	// String status = ActiveOrder.ACTIVEORDER_ACTIVESTATUS_PARTACTIVATED;
	// if (activeOrder.getTotalActiveSaleOrderCount() <= 0
	// && activeOrder.getTotalActiveSaleOrderAmount().compareTo(
	// BigInteger.ZERO) <= 0)
	// status = ActiveOrder.ACTIVEORDER_ACTIVATESTATUS_NONACTIVATED;
	// else if (activeOrder.getTotalActiveSaleOrderCount() >= activeOrder
	// .getTotalSaleOrderCount()
	// && activeOrder.getTotalActiveSaleOrderAmount().compareTo(
	// activeOrder.getTotalSaleOrderAmount()) >= 0)
	// status = ActiveOrder.ACTIVEORDER_ACTIVESTATUS_ALLACTIVATED;
	//
	// activeOrder.setActiveStatus(status);
	// activeOrderDaoImpl.updateActiveOrder(activeOrder);
	// }

	/**
	 * 销售机构信用度记帐
	 * 
	 * @param saleBranch
	 * @param tranDate
	 * @param amount
	 * @param saleOrderId
	 * @param activeOrderId
	 * @param operId
	 */
	private void saleBranchCreditAccount(SaleBranch saleBranch, Date tranDate,
			BigInteger amount, String tranType, BigInteger ticketId,
			BigInteger operId, Date curTime, String remark)
			throws PCPSApplicationException {

		// 检索
		saleBranch = saleBranchDaoImpl.getSaleBranchBySaleBranchNo(saleBranch
				.getSaleBranchNo());

		// 更新信用度余额
		BigInteger creditbal = saleBranch.getCredit().subtract(amount);
		if (creditbal.compareTo(saleBranch.getCreditLowLimit()) < 0)
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "销售机构" + saleBranch.getSaleBranchNo() + "信用度不足!");

		saleBranch.setCredit(creditbal);
		saleBranchDaoImpl.updateSaleBranch(saleBranch);

		// 记录机构资金明细
		SaleCapitalDetail saleCapitalDetail = new SaleCapitalDetail();

		saleCapitalDetail.setSaleBranchNo(saleBranch.getSaleBranchNo());
		saleCapitalDetail.setTranDate(tranDate);
		saleCapitalDetail.setTranTime(curTime);
		saleCapitalDetail.setTranType(tranType);
		saleCapitalDetail.setTicketId(ticketId);
		saleCapitalDetail.setCreditDeposit(BigInteger.ZERO);
		saleCapitalDetail.setCreditWithdraw(amount);
		saleCapitalDetail.setCashDeposit(BigInteger.ZERO);
		saleCapitalDetail.setCashWithdraw(BigInteger.ZERO);
		saleCapitalDetail.setOperId(operId);
		saleCapitalDetail.setRemark(remark);

		saleCapitalDetailDaoImpl.insertSaleCapitalDetail(saleCapitalDetail);
	}

	/**
	 * 计算销售单激活MAC
	 * 
	 * @param saleOrderId
	 * @param accSeqNo
	 * @param operId
	 * @return
	 */
	private String getSaleOrderActivateMac(BigInteger saleOrderId,
			String accSeqNo, BigInteger operId) {
		String macsrc = saleOrderId.toString() + accSeqNo + operId.toString();
		return new SHA1().getDigestOfString(macsrc.getBytes());
	}

	/**
	 * 激活销售单对销售机构记帐
	 * 
	 * @param saleBranch
	 * @param tranDate
	 * @param amount
	 * @param saleOrderId
	 * @param activeOrderId
	 * @param operId
	 */
	@SuppressWarnings("unused")
	private void saleBranchActivateAccount(SaleBranch saleBranch,
			Date tranDate, BigInteger amount, BigInteger saleOrderId,
			BigInteger activeOrderId, BigInteger operId, Date curTime)
			throws PCPSApplicationException {
		saleBranchCreditAccount(saleBranch, tranDate, amount,
				SaleCapitalDetail.TRANTYPE_ACTIVATE, saleOrderId, operId,
				curTime, "激活单ID:" + activeOrderId);
	}

	/**
	 * 删除为0的入口
	 * 
	 * @param allcardamt
	 */
	private void removeZeroEntry(Map<String, BigInteger> allcardamt) {
		Map<String, BigInteger> allzero = new HashMap<String, BigInteger>();

		for (Map.Entry<String, BigInteger> tot : allcardamt.entrySet()) {
			if (tot.getValue().compareTo(BigInteger.ZERO) <= 0)
				allzero.put(tot.getKey(), BigInteger.ZERO);
		}

		for (Map.Entry<String, BigInteger> zero : allzero.entrySet())
			allcardamt.remove(zero.getKey());
	}

	/**
	 * 计算Q值最大的1个卡号
	 * 
	 * @param alreadypaid
	 * @param allcardamt
	 * @return
	 */
	private String getMaxQValue(Map<String, BigInteger> alreadypaid,
			Map<String, BigInteger> allcardamt) {
		BigDecimal curmax = BigDecimal.ZERO;
		String cardNo = null;

		for (Map.Entry<String, BigInteger> allentry : allcardamt.entrySet()) {
			String cardno = allentry.getKey();
			BigInteger allamt = allentry.getValue();
			BigInteger allseat = alreadypaid.get(cardno);
			if (allseat == null)
				allseat = BigInteger.ZERO;
			allseat = allseat.add(BigInteger.ONE);
			BigDecimal allamt_q = new BigDecimal(allamt.toString());
			allamt_q = allamt_q.multiply(allamt_q);
			BigDecimal seat_q = new BigDecimal(allseat.toString())
					.multiply(new BigDecimal(allseat.add(BigInteger.ONE)
							.toString()));
			BigDecimal cmax = allamt_q
					.divide(seat_q, 6, RoundingMode.HALF_DOWN);
			if (cmax.compareTo(curmax) > 0) {
				cardNo = cardno;
				curmax = cmax;
			}
		}

		return cardNo;
	}

	/**
	 * 将指定银行指定金额公平分配到map中
	 * 
	 * @param bankid
	 * @param bankamt
	 * @param allcardamt
	 */
	private Map<String, BigInteger> distributePaid(BigInteger bankid,
			BigInteger bankamt, Map<String, BigInteger> allcardamt)
			throws PCPSApplicationException {

		Map<String, BigInteger> alreadypaid = new HashMap<String, BigInteger>();

		// 删除为0的入口数据
		removeZeroEntry(allcardamt);
		if (allcardamt.size() == 0)
			return alreadypaid;

		// 计算allcardamt的总和
		BigInteger total = BigInteger.ZERO;
		for (Map.Entry<String, BigInteger> tot : allcardamt.entrySet())
			total = total.add(tot.getValue());

		if (total.compareTo(BigInteger.ZERO) <= 0)
			return alreadypaid;

		// 先平均分配整数部分
		// 本笔银行付款信息折算到每分钱的贡献度
		BigDecimal bd = new BigDecimal(bankamt.toString()).divide(
				new BigDecimal(total.toString()), 10, RoundingMode.HALF_DOWN);

		for (Map.Entry<String, BigInteger> allentry : allcardamt.entrySet()) {
			String cardno = allentry.getKey();
			BigInteger cardamt = allentry.getValue();
			BigInteger curamt = bd.multiply(new BigDecimal(cardamt.toString()))
					.setScale(0, RoundingMode.HALF_UP).toBigInteger();
			// 折算后不足1分钱,继续
			if (curamt.compareTo(BigInteger.ZERO) <= 0)
				continue;
			BigInteger oldamt = alreadypaid.remove(cardno);
			if (oldamt == null)
				oldamt = BigInteger.ZERO;
			if (cardamt.compareTo(oldamt.add(curamt)) < 0)
				curamt = cardamt.subtract(oldamt);
			curamt = curamt.compareTo(bankamt) <= 0 ? curamt : bankamt;
			oldamt = oldamt.add(curamt);
			bankamt = bankamt.subtract(curamt);
			alreadypaid.put(cardno, oldamt);
			// 如果已经分配完毕
			if (bankamt.compareTo(BigInteger.ZERO) <= 0)
				break;
		}

		// 分配剩余部分,按Q值法,每次分配1分钱
		while (bankamt.compareTo(BigInteger.ZERO) > 0) {
			String cardno = getMaxQValue(alreadypaid, allcardamt);
			BigInteger oldamt = alreadypaid.remove(cardno);
			if (oldamt == null)
				oldamt = BigInteger.ZERO;
			oldamt = oldamt.add(BigInteger.ONE);
			alreadypaid.put(cardno, oldamt);
			bankamt = bankamt.subtract(BigInteger.ONE);
		}

		// 对alreadypaid中的每个记录,将allcardamt中的记录减去
		for (Map.Entry<String, BigInteger> allentry : alreadypaid.entrySet()) {
			String cardno = allentry.getKey();
			BigInteger amt = allentry.getValue();
			BigInteger oldamt = allcardamt.remove(cardno);
			if (oldamt == null)
				continue;
			oldamt = oldamt.subtract(amt);
			if (oldamt.compareTo(BigInteger.ZERO) <= 0)
				continue;
			allcardamt.put(cardno, oldamt);
		}

		return alreadypaid;
	}

	/**
	 * 获取有效的销售转账付款分配信息
	 * 
	 * @param saleOrder
	 *            销售单
	 * @param allcardamt
	 *            卡与开卡金额的map
	 * @param allpaidmap
	 *            转账分配map
	 * @return 总的现金付款额
	 * @throws PCPSApplicationException
	 */
	private BigInteger getValidatePaidMap(SaleOrder saleOrder,
			Map<String, BigInteger> allcardamt,
			Map<String, Map<BigInteger, BigInteger>> allpaidmap)
			throws PCPSApplicationException {

		List<SaleOrderPaidDetail> allpaiddetail = saleOrderPaidDetailDaoImpl
				.getSaleOrderPaidDetailListBySaleOrderId(saleOrder
						.getSaleOrderId());
		if (allpaiddetail == null)
			throw new PCPSApplicationException("", "销售单"
					+ saleOrder.getSaleOrderId() + "无有效的付款信息!");

		BigInteger totalcardamt = BigInteger.ZERO;
		// 计算allcardamt金额之和
		for (Map.Entry<String, BigInteger> cardentry : allcardamt.entrySet())
			totalcardamt = totalcardamt.add(cardentry.getValue());

		BigInteger cashpaid = BigInteger.ZERO;
		BigInteger transferpaid = BigInteger.ZERO;
		BigInteger totalpaid = BigInteger.ZERO;
		BigInteger totalfee = BigInteger.ZERO;
		BigInteger totalcardamtpaid = BigInteger.ZERO;

		Map<BigInteger, BigInteger> bankpaid = new HashMap<BigInteger, BigInteger>();

		// 计算总的付款情况
		for (SaleOrderPaidDetail sopd : allpaiddetail) {
			if (PCPSUtil.compareObject(sopd.getPaidClass(),
					SaleOrderPaidDetail.PAIDDETAIL_paidClass_sale))
				totalcardamtpaid = totalcardamtpaid.add(sopd.getPaidAmount());
			if (PCPSUtil.compareObject(sopd.getPaidClass(),
					SaleOrderPaidDetail.PAIDDETAIL_paidClass_fee)) {
				totalfee = totalfee.add(sopd.getPaidAmount());
				continue;
			}
			if (PCPSUtil.compareObject(sopd.getPaidType(),
					SaleOrderPaidDetail.PAIDDETAIL_PAIDTYPE_CASH))
				cashpaid = cashpaid.add(sopd.getPaidAmount());
			else if (PCPSUtil.compareObject(sopd.getPaidType(),
					SaleOrderPaidDetail.PAIDDETAIL_PAIDTYPE_CHECK)
					|| PCPSUtil
							.compareObject(
									sopd.getPaidType(),
									SaleOrderPaidDetail.PAIDDETAIL_PAIDTYPE_BANKTRANSFER)) {
				transferpaid = transferpaid.add(sopd.getPaidAmount());
				BigInteger paccid = sopd.getPaidAccountId();
				if (paccid == null)
					paccid = BigInteger.ZERO;
				BigInteger curbankpaid = bankpaid.remove(paccid);
				if (curbankpaid == null)
					curbankpaid = BigInteger.ZERO;
				curbankpaid = curbankpaid.add(sopd.getPaidAmount());
				// 仅保存有效的付款银行帐户信息
				if (curbankpaid.compareTo(BigInteger.ZERO) != 0)
					bankpaid.put(paccid, curbankpaid);
			} else
				throw new PCPSApplicationException("", "销售单"
						+ saleOrder.getSaleOrderId() + "存在无效的付款类型"
						+ sopd.getPaidType() + "!");
		}

		totalpaid = cashpaid.add(transferpaid);

		// 针对授信购卡特殊处理
		if (PCPSUtil.compareObject(SaleOrder.SaleOrder_PaidType_Credit,
				saleOrder.getPaidType())) {
			totalcardamtpaid = totalcardamt;
			totalfee = saleOrder.getFactFee();
			totalpaid = totalcardamtpaid.add(totalfee);
			cashpaid = totalcardamtpaid;
		}

		// 现金视为特殊的ID
		bankpaid.put(BigInteger.ZERO, cashpaid);

		// 不能存在非法的付款信息
		if (cashpaid.compareTo(BigInteger.ZERO) < 0
				|| transferpaid.compareTo(BigInteger.ZERO) < 0
				|| totalpaid.compareTo(BigInteger.ZERO) < 0
				|| totalfee.compareTo(BigInteger.ZERO) < 0
				|| totalcardamt.compareTo(saleOrder.getTotalSaleAmount()) != 0
				|| totalcardamtpaid.compareTo(totalcardamt) != 0
				|| totalfee.compareTo(saleOrder.getFactFee()) != 0
				|| ((totalcardamtpaid.add(totalfee).compareTo(
						saleOrder.getAlreayPaidAmount()) != 0) && PCPSUtil
						.compareObject(SaleOrder.SaleOrder_PaidType_Normal,
								saleOrder.getPaidType())))
			throw new PCPSApplicationException("", "销售单"
					+ saleOrder.getSaleOrderId() + "付款信息有误!");

		// 产生工作对象
		Map<String, BigInteger> allcardamt_work = new HashMap<String, BigInteger>();
		for (Map.Entry<String, BigInteger> allentry : allcardamt.entrySet())
			allcardamt_work.put(allentry.getKey(), allentry.getValue());

		// 将转账信息平均分配到每一个卡号,最后一个卡号在本帐号的付款金额采用减法计算
		for (Map.Entry<BigInteger, BigInteger> bankpaidentry : bankpaid
				.entrySet()) {
			BigInteger bankpaidamt = bankpaidentry.getValue();
			int result = bankpaidamt.compareTo(BigInteger.ZERO);
			if (result == 0)
				continue;
			if (result < 0)
				throw new PCPSApplicationException("", "销售单"
						+ saleOrder.getSaleOrderId() + "付款帐户总付款信息有误!");

			Map<String, BigInteger> alreadypaid = distributePaid(bankpaidentry
					.getKey(), bankpaidamt, allcardamt_work);

			// 加入到返回列表
			for (Map.Entry<String, BigInteger> allentry : alreadypaid
					.entrySet()) {
				Map<BigInteger, BigInteger> curbank = allpaidmap.get(allentry
						.getKey());
				if (curbank == null) {
					curbank = new HashMap<BigInteger, BigInteger>();
					allpaidmap.put(allentry.getKey(), curbank);
				}
				curbank.put(bankpaidentry.getKey(), allentry.getValue());
			}
		}

		return cashpaid;
	}

	/**
	 * 燃气加气卡激活销售单
	 * 
	 * @param saleOrderId
	 *            销售单ID
	 * @param operId
	 *            操作员ID(发卡商或发卡商分支机构的操作员)
	 */
	@Override
	public void activateAppManageSaleOrder(BigInteger saleOrderId,
			BigInteger operId) throws PCPSApplicationException {

		// 参数检查
		if (saleOrderId == null || operId == null)
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "无效的调用参数!");

		// 取操作员号
		SysOpUser sysOpUser = sysOpUserDaoImpl.getSysOpUserByOperId(operId);
		if (sysOpUser == null)
			throw new CardTranApplicationException("", "无效的操作员!");

		String curbrchno = sysOpUser.getOperBranchNo();

		// 系统机构号 -- 确定机构类型
		SysBranch sysBranch = sysBranchDaoImpl
				.getSysBranchByBranchNo(curbrchno);

		if (!PCPSUtil.compareObject(sysBranch.getBranchType(),
				SysBranch.SYSBRANCH_SALEBRANCH))
			throw new CardTranApplicationException("", "必须是销售商分支机构的操作员!");

		// 取发卡商信息
		IssueCompany issueCompany = issueCompanyDaoImpl
				.getIssueCompanyByIssueCompanyNo(PCPSUtil
						.getICNoByBranchNo(curbrchno));

		// 取销售单信息
		SaleOrder saleOrder = getValidSaleOrderBySaleOrderId(saleOrderId);

		// 取销售机构信息
		// SaleBranch saleBranch = getValidSaleBranchBySaleBranchNo(saleOrder
		// .getSaleBranchNo());

		// 取销售商号
		// SaleCompany saleCompany =
		// getValidSaleCompanyBySaleBranchNo(saleBranch);

		// 检查是否可以激活
		// canActivateSaleOrder(issueCompany, saleOrder, saleCompany,
		// saleBranch);

		// 获得完整的售卡列表
		Map<String, BigInteger> allcardamt = new HashMap<String, BigInteger>();
		Map<String, BigInteger> allcardclassic = new HashMap<String, BigInteger>();
		Map<String, CardStock> allcard = getAppManageCardOfSaleOrder(saleOrder,
				allcardamt, allcardclassic);

		if (allcard.size() != 1) {
			throw new CardTranApplicationException("", "每次销售只可售一张卡!");
		}

		// 获取完整的销售员列表
		// ArrayList<SalesGroup> sglist = getValidSalesBySaleOrder(saleOrder);

		// 获得实名制信息
		Map<String, BigInteger> allcardowner = getAllCardOwnerOfSaleOrder(saleOrder);

		// 将转账付款信息分配到每一个卡上
		// Map<String, Map<BigInteger, BigInteger>> allpaidmap = new
		// HashMap<String, Map<BigInteger, BigInteger>>();

		// 本销售单现金总付款金额
		// getValidatePaidMap(saleOrder, allcardamt, allpaidmap);

		// 准备开户信息
		ArrayList<OpenAccountParam> oaplist = generateAppManageOpenAccountCards(
				saleOrder, allcard, allcardowner, allcardamt);

		// 取当前时间
		Date acttime = pcpsCommonDaoImpl.getDatabaseSysTime();

		// 发卡商分支机构激活额度记帐 -- 仅与销售金额有关
		// if (saleOrder.getTotalSaleAmount().compareTo(BigInteger.ZERO) != 0)
		// issueBranchBusinessImpl.activateAccount(curbrchno,
		// CreditAccDetail.use_Ac_Bal, saleOrder.getTotalSaleAmount(),
		// CreditAccDetail.orderType_SALE, saleOrderId, operId);

		// 先将卡信息生成ActivateCard
		Map<String, ActivateCard> allacmap = generateActivateCard(acttime,
				saleOrder, allcard, allcardowner, allcardamt, allcardclassic);

		// 执行开户
		OpenAccountResult oresult = accountBusinessImpl.OpenAppManageAccount(
				issueCompany.getIssueCompanyNo(), saleOrder.getSaleBranchNo(),
				saleOrderId, issueCompany.getTranDate(), acttime, "SALE_"
						+ saleOrder.getSaleOrderId().toString(), operId, "开户",
				oaplist);

		// 将生成的主帐号信息更新到ActivateCard中
		ArrayList<OpenAccountResult_> opAccList = oresult.accresult;
		if (opAccList.size() != 2) {
			throw new CardTranApplicationException("", "主账户钱包账户开户数据错误!");
		}

		ActivateCard ac = allacmap.get(opAccList.get(0).cardNo);
		ac.setMasterAccNo(opAccList.get(0).masterAccNo);
		ac.setWalletAccNo(opAccList.get(1).masterAccNo);
		activateCardDaoImpl.update(ac);

		// 登记销售单状态转移明细
		SaleOrderActionDetail saleOrderActionDetail = new SaleOrderActionDetail();
		saleOrderActionDetail.setSaleOrderId(saleOrder.getSaleOrderId());
		saleOrderActionDetail.setActionTime(acttime);
		saleOrderActionDetail.setOperId(operId);
		saleOrderActionDetail.setInitialStatus(saleOrder.getOrderStatus());
		saleOrderActionDetail
				.setEndStatus(SaleOrder.SALEORDER_ORDERSTATUS_ACTIVATED);
		saleOrderActionDetail
				.setActionType(SaleOrderActionDetail.ACTIONTYPE_CONFIRMACTIVATION);
		saleOrderActionDetail.setRemark("销售单ID:" + saleOrderId.toString()
				+ " 帐务流水号:" + oresult.accSeqNo);
		saleOrderActionDetailDaoImpl
				.insertSaleOrderActionDetail(saleOrderActionDetail);

		// 修正销售单状态
		String lastActiveMac = getSaleOrderActivateMac(saleOrder
				.getSaleOrderId(), oresult.accSeqNo, operId);

		saleOrder.setLastActiveAccSeqNo(oresult.accSeqNo);
		saleOrder.setOrderStatus(SaleOrder.SALEORDER_ORDERSTATUS_ACTIVATED);
		saleOrder.setLastActiveMac(lastActiveMac);
		saleOrder.setAuthOperId(operId.intValue());// 终审人员
		saleOrderDaoImpl.updateSaleOrder(saleOrder);

		// 从库存表中真正删除
		removeAllActivateCard(allcard);

		// 更新激活单状态&汇总数据
		// handleActivateOrder(activeOrder, saleOrder.getTotalSaleAmount(),
		// acttime);
	}

	// ===================================start
	/**
	 * 测试激活MakeCardControl
	 * 
	 * @param batchNo
	 * @param operid
	 * @throws PCPSApplicationException
	 */
	@Override
	public void activateMakeCardControl(String key, String batchNo)
			throws PCPSApplicationException {
		if (!key.equals("turing")) {
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "无效的调用参数!" + key);
		}

		Date now = pcpsCommonDaoImpl.getDatabaseSysTime();
		List<NonEntityCard> necList = creatMakeCard(batchNo);
		NonEntityCard nec = null;
		MasterAccount ma = null;
		BigInteger maNo = null;
		SubAccount subacc = null;
		BigInteger balance = new BigInteger("100000");
		BigInteger faceId = new BigInteger("1487");
		BigInteger classicId = new BigInteger("1479");
		BigInteger saleOrderId = new BigInteger("249926");
		BigInteger buyId = new BigInteger("5344");
		ActivateCard ac = null;
		// long l = System.currentTimeMillis();
		// System.out.println("开卡开始====" + batchNo);
		for (int i = 0; i < necList.size(); i++) {
			nec = necList.get(i);
			ma = getMasterAccount(now, nec.getCardNo(), balance);
			maNo = ma.getMasterAccNo();
			// 主账户
			masterAccountDaoImpl.insert(ma);
			// 子账户
			subacc = getSubAccount(maNo, now, balance);
			subAccountDaoImpl.insert(subacc);

			ac = getActivateCard(batchNo, nec, maNo, faceId, classicId,
					saleOrderId, buyId, balance, now);
			// 插入到激活卡列表
			activateCardDaoImpl.insert(ac);
		}
		// System.out.println(batchNo + "结束====耗时："
		// + (System.currentTimeMillis() - l) / 1000);
	}

	private ActivateCard getActivateCard(String batchNo, NonEntityCard nec,
			BigInteger maNo, BigInteger faceId, BigInteger classicId,
			BigInteger saleOrderId, BigInteger buyId, BigInteger balance,
			Date now) {
		ActivateCard ac = new ActivateCard();
		ac.setBatchNo(batchNo);
		ac.setOpenBranchNo("961880980161");
		ac.setCardSeqNo(nec.getCardSeqNo());
		ac.setCardNo(nec.getCardNo());
		ac.setCardFaceId(faceId);
		ac.setCardClassicId(classicId);
		ac.setMasterAccNo(maNo); // 先置为null,开户成功后再置为真正的主帐号
		ac.setWalletAccNo(null);// 钱包账户
		ac.setWalletBalance(BigInteger.ZERO);// 钱包余额
		ac.setCardPwd(nec.getCardPwd());
		ac.setTwoTrackContent(nec.getTwoTrackContent());
		ac.setThirdTrackContent(nec.getThirdTrackContent());
		ac.setSaleBranchNo("961880980161");
		ac.setSaleOrderId(saleOrderId);
		ac.setBuyerId(buyId);
		ac.setOwnerId(buyId);
		ac.setInitialBalance(balance);
		// 销售时不计开户金额到累计充值字段
		ac.setTotalDeposit(BigInteger.ZERO);
		ac.setBalance(balance);
		ac.setExpired(null);
		ac.setPwdErrCnt(0);
		ac.setLastPwdErrTime(null);
		ac.setOpenTime(now);
		ac.setOpenStatus(ActivateCard.ACTIVATECARD_OPENSTATUS_NORMAL);
		ac.setCloseStatus(ActivateCard.ACTIVATECARD_CLOSESTATUS_NORMAL);
		ac.setLastLossTime(null);
		ac.setLossStatus(ActivateCard.ACTIVATECARD_LOSSSTATUS_NORMAL);
		ac
				.setManualLockStatus(ActivateCard.ACTIVATECARD_MANUALLOCKSTATUS_UNLOCK);

		// 计算卡激活MAC
		String activateMac = getActivateCardMac(ac.getSaleOrderId(), ac
				.getCardNo(), ac.getBalance(), ac.getExpired(), ac.getCardPwd());

		ac.setActivateMac(activateMac);
		// 累计消费次数
		ac.setTotalConsumeCount(BigInteger.ZERO);

		return ac;
	}

	@EJB(mappedName = "account.impl.MasterAccountDaoImpl")
	private MasterAccountDao masterAccountDaoImpl;

	/**
	 * 创建主帐户
	 * 
	 * @param issueCompanyNo
	 * @return
	 */
	private MasterAccount getMasterAccount(Date openTime, String cardNo,
			BigInteger balance) throws PCPSApplicationException {
		// 产生主帐号
		BigInteger masterAccNo = pcpsCommonDaoImpl.getUniqueIntegerKey();
		// 设置记表参数
		MasterAccount masteracc = new MasterAccount();
		masteracc.setMasterAccNo(masterAccNo);
		masteracc.setIssueCompanyNo("961880");
		masteracc.setCardNo(cardNo);
		masteracc.setOwnerId(null);
		masteracc.setBalance(balance);
		masteracc.setOpenTime(openTime);
		masteracc.setLastAccountTime(openTime);
		masteracc.setOpenStatus(MasterAccount.MASTERACCOUNT_OPENSTATUS_NORMAL);
		masteracc.setCloseStatus(MasterAccount.MASTERACCOUNT_CLOSESTATUS_NONE);
		masteracc.setFreeze(MasterAccount.MASTERACCOUNT_FREEZE_NONE);
		masteracc.setFreezeAmount(BigInteger.ZERO);
		masteracc.setAuthDeposit(BigInteger.ZERO);
		masteracc.setAuthRedemp(BigInteger.ZERO);
		masteracc.setStopPayment(MasterAccount.MASTERACCOUNT_STOPPAYMENT_NONE);
		masteracc.setRemark(null);
		return masteracc;
	}

	@EJB(mappedName = "account.impl.SubAccountDaoImpl")
	private SubAccountDao subAccountDaoImpl;

	private SubAccount getSubAccount(BigInteger masterAccNo, Date openTime,
			BigInteger balance) throws PCPSApplicationException {
		// 产生子帐号
		BigInteger subAccNo = pcpsCommonDaoImpl.getUniqueIntegerKey();
		// 设置记表参数
		SubAccount subacc = new SubAccount();
		subacc.setSubAccNo(subAccNo);
		subacc.setMasterAccNo(masterAccNo);
		subacc.setOpenBranchNo("961880980161");
		subacc.setOpenTime(openTime);
		subacc.setLastAccountTime(openTime);
		subacc.setSalesGroupId(null);
		subacc.setBalance(balance);
		return subacc;
	}

	/**
	 * 产生制卡信息集合,返回装有NonEntityCard实体的list集合
	 */

	private List<NonEntityCard> creatMakeCard(String batchNo)
			throws PCPSApplicationException {
		List<NonEntityCard> list = new ArrayList<NonEntityCard>();
		int i = 0;
		int count = 3000;
		BigInteger id = null;
		HashMap<String, String> hm = new HashMap<String, String>();
		do {
			id = new BigInteger(30, 10, (new Random(System.currentTimeMillis()
					+ i)));
			String sid = id.toString();
			sid = sid.substring(1, 8);
			boolean ishave = hm.containsValue(sid);
			if (!ishave) {
				hm.put(String.valueOf(i), sid);
				i++;
			}
		} while (i < count);
		for (int j = 0; j < hm.size(); j++) {
			NonEntityCard nec = new NonEntityCard();
			nec.setBatchNo(batchNo);
			String seqno = String.valueOf(j + 1);
			while (seqno.length() < 6) {
				seqno = "0" + seqno;
			}
			nec.setCardSeqNo(batchNo + seqno);
			nec.setCardNo(batchNo + hm.get(String.valueOf(j)));
			// 随即8密码
			nec.setCardPwd(new SHA1()
					.getDigestOfString((nec.getCardNo() + "00000000")
							.getBytes()));
			nec.setTwoTrackContent(nec.getCardNo());
			nec.setThirdTrackContent(nec.getCardNo() + "=000029"
					+ (nec.getCardNo() + "0000029") + "00000000");
			list.add(nec);
		}
		return list;
	}

	// ============================================end
	/**
	 * 激活销售单
	 * 
	 * @param saleOrderId
	 *            销售单ID
	 * @param operId
	 *            操作员ID(发卡商或发卡商分支机构的操作员)
	 */
	public void activateSaleOrder(PCPSWebInput webInput,
			BigInteger saleOrderId, BigInteger operId)
			throws PCPSApplicationException {

		// 参数检查
		if (saleOrderId == null || operId == null)
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "无效的调用参数!");

		// 取操作员号
		SysOpUser sysOpUser = sysOpUserDaoImpl.getSysOpUserByOperId(operId);
		if (sysOpUser == null)
			throw new CardTranApplicationException("", "无效的操作员!");

		String curbrchno = sysOpUser.getOperBranchNo();

		// 系统机构号 -- 确定机构类型
		SysBranch sysBranch = sysBranchDaoImpl
				.getSysBranchByBranchNo(curbrchno);

		if (!PCPSUtil.compareObject(sysBranch.getBranchType(),
				SysBranch.SYSBRANCH_ISSUEBRANCH))
			throw new CardTranApplicationException("", "必须是发卡商分支机构的操作员!");

		// 取发卡商信息
		IssueCompany issueCompany = issueCompanyDaoImpl
				.getIssueCompanyByIssueCompanyNo(PCPSUtil
						.getICNoByBranchNo(curbrchno));

		// 取销售单信息
		SaleOrder saleOrder = getValidSaleOrderBySaleOrderId(saleOrderId);

		// 取销售机构信息
		SaleBranch saleBranch = getValidSaleBranchBySaleBranchNo(saleOrder
				.getSaleBranchNo());

		// 取销售商号
		// SaleCompany saleCompany =
		// getValidSaleCompanyBySaleBranchNo(saleBranch);

		// 检查是否可以激活
		canActivateSaleOrder(issueCompany, saleOrder, saleBranch);

		// 检查激活机构号是否与当前操作员所在的机构号一致
		if (!PCPSUtil.compareObject(saleOrder.getActivateBranchNo(), curbrchno))
			throw new CardTranApplicationException("", "本销售单提交激活机构非本机构!");

		// 获得完整的售卡列表
		Map<String, BigInteger> allcardamt = new HashMap<String, BigInteger>();
		Map<String, BigInteger> allcardclassic = new HashMap<String, BigInteger>();
		Map<String, CardStock> allcard = getAllCardOfSaleOrder(saleOrder,
				allcardamt, allcardclassic);

		// 获取完整的销售员列表
		ArrayList<SalesGroup> sglist = getValidSalesBySaleOrder(saleOrder);

		// 获得实名制信息
		Map<String, BigInteger> allcardowner = getAllCardOwnerOfSaleOrder(saleOrder);

		// 将转账付款信息分配到每一个卡上
		Map<String, Map<BigInteger, BigInteger>> allpaidmap = new HashMap<String, Map<BigInteger, BigInteger>>();

		// 本销售单现金总付款金额
		getValidatePaidMap(saleOrder, allcardamt, allpaidmap);

		for (Map.Entry<String, Map<BigInteger, BigInteger>> entry : allpaidmap.entrySet()) {
			PCPSUtil.Log("============="+entry.getKey());
			for (Map.Entry<BigInteger, BigInteger> entr : entry.getValue().entrySet()) {
				PCPSUtil.Log("============="+entr.getKey()+"---------"+entr.getValue());
			}
		}
		// 准备开户信息
		ArrayList<OpenAccountParam> oaplist = generateAllOpenAccountCards(
				saleOrder, allcard, allcardowner, allcardamt);

		// 取当前时间
		Date acttime = pcpsCommonDaoImpl.getDatabaseSysTime();

		// 先将卡信息生成ActivateCard
		Map<String, ActivateCard> allacmap = generateActivateCard(acttime,
				saleOrder, allcard, allcardowner, allcardamt, allcardclassic);

		// 执行开户
		OpenAccountResult oresult = accountBusinessImpl.OpenAccount(
				issueCompany.getIssueCompanyNo(), saleOrder.getSaleBranchNo(),
				saleOrderId, issueCompany.getTranDate(), acttime, "SALE_"
						+ saleOrder.getSaleOrderId().toString(), operId, "开户",
				oaplist, sglist, allpaidmap);

		// 将生成的主帐号信息更新到ActivateCard中
		for (OpenAccountResult.OpenAccountResult_ oar : oresult.accresult) {
			ActivateCard ac = allacmap.get(oar.cardNo);
			ac.setMasterAccNo(oar.masterAccNo);
			activateCardDaoImpl.update(ac);
		}

		// 登记销售单状态转移明细
		SaleOrderActionDetail saleOrderActionDetail = new SaleOrderActionDetail();
		saleOrderActionDetail.setSaleOrderId(saleOrder.getSaleOrderId());
		saleOrderActionDetail.setActionTime(acttime);
		saleOrderActionDetail.setOperId(operId);
		saleOrderActionDetail
				.setInitialStatus(SaleOrder.SaleOrder_OrderStatus_Sent);
		saleOrderActionDetail
				.setEndStatus(SaleOrder.SALEORDER_ORDERSTATUS_ACTIVATED);
		saleOrderActionDetail
				.setActionType(SaleOrderActionDetail.ACTIONTYPE_CONFIRMACTIVATION);
		saleOrderActionDetail.setRemark("销售单ID:" + saleOrderId.toString()
				+ " 帐务流水号:" + oresult.accSeqNo);
		saleOrderActionDetailDaoImpl
				.insertSaleOrderActionDetail(saleOrderActionDetail);

		// 修正销售单状态
		String lastActiveMac = getSaleOrderActivateMac(saleOrder
				.getSaleOrderId(), oresult.accSeqNo, operId);

		saleOrder.setLastActiveAccSeqNo(oresult.accSeqNo);
		saleOrder.setOrderStatus(SaleOrder.SALEORDER_ORDERSTATUS_ACTIVATED);
		saleOrder.setLastActiveMac(lastActiveMac);
		saleOrder.setAuthOperId(operId.intValue());// 终审人员

		// 2013.07.13 add by yxb
		saleOrder.setLastActiveDate(issueCompany.getTranDate());

		saleOrderDaoImpl.updateSaleOrder(saleOrder);

		// 日志记录
		sysOperLogDaoImpl.insertSysOperLogInfo(webInput,
				SysOperLog.operType_Edit, "激活销售单", "SaleOrderId: "
						+ saleOrder.getSaleOrderId());

		// 从库存表中循环所有卡号真正删除。屏蔽
		// removeAllActivateCard(allcard);

		// 根据售卡号段从表中真正删除
		removeAllActivateCard(saleOrderId);

		// 发卡商分支机构激活额度记帐 -- 仅与销售金额有关
		if (saleOrder.getTotalSaleAmount().compareTo(BigInteger.ZERO) != 0)
			issueBranchBusinessImpl.activateAccount(curbrchno,
					CreditAccDetail.use_Ac_Bal, saleOrder.getTotalSaleAmount(),
					CreditAccDetail.orderType_SALE, saleOrderId, operId);

		// 更新激活单状态&汇总数据
		// handleActivateOrder(activeOrder, saleOrder.getTotalSaleAmount(),
		// acttime);
	}

	/**
	 * 根据saleOrderId检索ActivateCard列表
	 * 
	 * @param saleOrder
	 * @return
	 * @throws PCPSApplicationException
	 */
	private Map<String, ActivateCard> getAllValidActivateCard(
			SaleOrder saleOrder) throws PCPSApplicationException {

		Map<String, ActivateCard> allcardmap = new HashMap<String, ActivateCard>();
		List<ActivateCard> cardlist = activateCardDaoImpl
				.getAllActivateCardListBySaleOrderId(saleOrder.getSaleOrderId());
		if (cardlist == null || cardlist.size() < 1)
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "激活卡列表销售单ID" + saleOrder.getSaleOrderId().toString()
							+ "不存在!");
		if (cardlist.size() != saleOrder.getTotalCardCount())
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "销售单ID" + saleOrder.getSaleOrderId().toString()
							+ "所列卡数目与激活卡列表不符!");
		BigInteger bal = BigInteger.ZERO;
		for (ActivateCard ac : cardlist) {
			bal = bal.add(ac.getBalance());
			// 逐一验证
			String activateMac = getActivateCardMac(saleOrder.getSaleOrderId(),
					ac.getCardNo(), ac.getBalance(), ac.getExpired(), ac
							.getCardPwd());
			if (!PCPSUtil.compareObject(activateMac, ac.getActivateMac()))
				throw new CardTranApplicationException(
						CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
						"", "激活卡" + ac.getCardNo() + "发生了变化,不允许撤销激活!");
			allcardmap.put(ac.getCardNo(), ac);
		}

		if (bal.compareTo(saleOrder.getTotalSaleAmount()) != 0)
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "销售单ID" + saleOrder.getSaleOrderId().toString()
							+ "合计金额与激活卡列表合计金额不符!");

		return allcardmap;
	}

	/**
	 * 重新进入卡库存表
	 * 
	 * @param csmap
	 * @throws PCPSApplicationException
	 */
	private void reEnterSaleStock(ActivateCard ac)
			throws PCPSApplicationException {
		CardStock cs = new CardStock();
		cs.setBatchNo(ac.getBatchNo());
		cs.setCardNo(ac.getCardNo());
		cs.setCardPwd(ac.getCardPwd());
		cs.setCardSeqNo(ac.getCardSeqNo());
		cs.setIssueBranchNo(null);
		cs.setSaleBranchNo(ac.getSaleBranchNo());
		cs.setTwoTrackContent(ac.getTwoTrackContent());
		cs.setThirdTrackContent(ac.getThirdTrackContent());
		cs.setStatus(CardStock.CARDSTOCK_STATUS_ACTIVATECANCEL);
		cardStockDaoImpl.insertCardStock(cs);
	}

	/**
	 * 获取某销售单现金付款总额
	 * 
	 * @param saleOrder
	 *            销售单
	 * @return 总的现金付款额
	 * @throws PCPSApplicationException
	 */
	@SuppressWarnings("unused")
	private BigInteger getSaleOrderTotalCash(SaleOrder saleOrder)
			throws PCPSApplicationException {

		List<SaleOrderPaidDetail> allpaiddetail = saleOrderPaidDetailDaoImpl
				.getSaleOrderPaidDetailListBySaleOrderId(saleOrder
						.getSaleOrderId());
		if (allpaiddetail == null)
			throw new PCPSApplicationException("", "销售单"
					+ saleOrder.getSaleOrderId() + "无有效的付款信息!");

		BigInteger cashpaid = BigInteger.ZERO;

		// 计算总的付款情况
		for (SaleOrderPaidDetail sopd : allpaiddetail) {
			if (PCPSUtil.compareObject(sopd.getPaidType(),
					SaleOrderPaidDetail.PAIDDETAIL_PAIDTYPE_CASH)
					|| PCPSUtil.compareObject(sopd.getPaidType(),
							SaleOrderPaidDetail.PAIDDETAIL_PAIDTYPE_CHECK))
				cashpaid = cashpaid.add(sopd.getPaidAmount());
		}

		return cashpaid;
	}

	/**
	 * 撤销激活销售单
	 * 
	 * @param saleOrderId
	 *            销售单ID
	 * @param operId
	 *            操作员ID
	 * @param userRemark
	 *            撤销激活原因
	 */
	public void cancelActivateSaleOrder(PCPSWebInput webInput,
			BigInteger saleOrderId, BigInteger operId, String userRemark)
			throws PCPSApplicationException {

		// 参数检查
		if (saleOrderId == null || operId == null)
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "无效的调用参数!");

		// 用户备注检查
		if (PCPSUtil.isEmpty(userRemark))
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "必须填写撤销激活原因!");

		// 取操作员号
		SysOpUser sysOpUser = sysOpUserDaoImpl.getSysOpUserByOperId(operId);
		if (sysOpUser == null)
			throw new CardTranApplicationException("", "无效的操作员!");

		String curbrchno = sysOpUser.getOperBranchNo();

		// 取发卡商信息
		IssueCompany issueCompany = issueCompanyDaoImpl
				.getIssueCompanyByIssueCompanyNo(PCPSUtil
						.getICNoByBranchNo(curbrchno));

		// 取销售单信息
		SaleOrder saleOrder = getValidSaleOrderBySaleOrderId(saleOrderId);

		if (!(PCPSUtil.compareObject(saleOrder.getOrderStatus(),
				SaleOrder.SALEORDER_ORDERSTATUS_ACTIVATED) || PCPSUtil
				.compareObject(saleOrder.getOrderStatus(),
						SaleOrder.SALEORDER_ORDERSTATUS_UNDOFREEZE)))
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "销售单" + saleOrder.getSaleOrderId() + "状态错误,无法撤销激活!");

		// 非销售单上指定的激活机构操作员 谁录入谁撤销
		// if (!PCPSUtil.compareObject(sysOpUser.getOperBranchNo(), saleOrder
		// .getActivateBranchNo()))
		// throw new CardTranApplicationException(
		// CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
		// "", "销售单" + saleOrder.getSaleOrderId()
		// + "激活机构与操作员所在机构不一致,无法撤销激活!");

		// 验证能否撤销
		String lastActiveMac = getSaleOrderActivateMac(saleOrder
				.getSaleOrderId(), saleOrder.getLastActiveAccSeqNo(), operId);
		if (!PCPSUtil
				.compareObject(lastActiveMac, saleOrder.getLastActiveMac()))
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "销售单" + saleOrder.getSaleOrderId() + "MAC验证错,无法撤销激活!");

		// 根据saleOrderId检索ActivateCard
		Map<String, ActivateCard> allcard = getAllValidActivateCard(saleOrder);

		// 取当前时间
		Date acttime = pcpsCommonDaoImpl.getDatabaseSysTime();

		// 机构信用度记帐
		issueBranchBusinessImpl.activateAccount(
				saleOrder.getActivateBranchNo(), CreditAccDetail.use_Ac_Bal,
				BigInteger.ZERO.subtract(saleOrder.getTotalSaleAmount()),
				CreditAccDetail.orderType_SALE, saleOrderId, operId);

		// 执行开户取消
		String accseqno = accountBusinessImpl.OpenAccountCancel(issueCompany
				.getIssueCompanyNo(), issueCompany.getTranDate(), acttime,
				saleOrder.getSaleOrderId().toString(), saleOrder
						.getLastActiveAccSeqNo(), operId, "开户撤销");

		// 删除所有的ActivateCard
		for (Map.Entry<String, ActivateCard> acme : allcard.entrySet()) {
			ActivateCard ac = acme.getValue();
			activateCardDaoImpl.remove(ac);
			// 重新加入到库存表中
			reEnterSaleStock(ac);
		}

		// 登记销售单状态转移明细
		SaleOrderActionDetail saleOrderActionDetail = new SaleOrderActionDetail();
		saleOrderActionDetail.setSaleOrderId(saleOrder.getSaleOrderId());
		saleOrderActionDetail.setActionTime(acttime);
		saleOrderActionDetail.setOperId(operId);
		saleOrderActionDetail.setInitialStatus(saleOrder.getOrderStatus());
		saleOrderActionDetail
				.setEndStatus(SaleOrder.SALEORDER_ORDERSTATUS_LIBRARY);
		saleOrderActionDetail
				.setActionType(SaleOrderActionDetail.ACTIONTYPE_DEACTIVATE);
		saleOrderActionDetail.setRemark(userRemark + "撤销帐务流水号:" + accseqno);
		saleOrderActionDetailDaoImpl
				.insertSaleOrderActionDetail(saleOrderActionDetail);

		// 修正销售单状态
		saleOrder.setLastCancelActiveAccSeqNo(accseqno);
		saleOrder.setOrderStatus(SaleOrder.SALEORDER_ORDERSTATUS_LIBRARY);

		// 2013.07.13 add by yxb
		saleOrder.setLastCancelActiveDate(issueCompany.getTranDate());

		saleOrderDaoImpl.updateSaleOrder(saleOrder);

		// 日志记录
		sysOperLogDaoImpl.insertSysOperLogInfo(webInput,
				SysOperLog.operType_Edit, "撤销激活销售单", "SaleOrderId: "
						+ saleOrder.getSaleOrderId());
		// 更新激活单状态&汇总数据
		// handleActivateOrder(activeOrder, BigInteger.ZERO.subtract(saleOrder
		// .getTotalSaleAmount()), acttime);
	}

	/**
	 * 检查冻结解冻参数,并返回销售单对象
	 * 
	 * @param saleOrderId
	 * @param operId
	 * @param userRemark
	 * @return
	 * @throws PCPSApplicationException
	 */
	private SaleOrder checkFreezeSaleOrderArgs(BigInteger saleOrderId,
			BigInteger operId, String userRemark)
			throws PCPSApplicationException {
		// 参数检查
		if (saleOrderId == null || operId == null)
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "无效的调用参数!");

		// 用户备注检查
		if (PCPSUtil.isEmpty(userRemark))
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "必须填写冻结/解冻原因!");

		// 取发卡商信息
		IssueCompany issueCompany = getValidIssueCompanyByOperId(operId);

		// 取销售单信息
		SaleOrder saleOrder = getValidSaleOrderBySaleOrderId(saleOrderId);

		// 取销售机构信息
		SaleBranch saleBranch = getValidSaleBranchBySaleBranchNo(saleOrder
				.getSaleBranchNo());

		// 取销售商号
		// SaleCompany saleCompany =
		// getValidSaleCompanyBySaleBranchNo(saleBranch);

		String issueCompanyNo = issueCompany.getIssueCompanyNo();

		// 必须与issueCompany一致
		if (!PCPSUtil.compareObject(issueCompanyNo, PCPSUtil
				.getICNoByBranchNo(saleBranch.getIssueBranchNo())))
			invalidIssueCompany(issueCompanyNo);

		return saleOrder;
	}

	/**
	 * 冻结已激活销售单
	 * 
	 * @param saleOrderId
	 *            销售单ID
	 * @param operId
	 *            操作员ID
	 * @param remark
	 *            冻结原因
	 */
	public void freezeSaleOrder(PCPSWebInput webInput, BigInteger saleOrderId,
			BigInteger operId, String userRemark)
			throws PCPSApplicationException {

		// 参数检查
		SaleOrder saleOrder = checkFreezeSaleOrderArgs(saleOrderId, operId,
				userRemark);

		// 检查销售单状态 -- 必须处于激活态或解冻结状态
		if (!(PCPSUtil.compareObject(saleOrder.getOrderStatus(),
				SaleOrder.SALEORDER_ORDERSTATUS_ACTIVATED) || PCPSUtil
				.compareObject(saleOrder.getOrderStatus(),
						SaleOrder.SALEORDER_ORDERSTATUS_UNDOFREEZE)))
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "销售单状态不允许!");

		// 取当前时间
		Date acttime = pcpsCommonDaoImpl.getDatabaseSysTime();

		// 登记销售单状态转移明细
		SaleOrderActionDetail saleOrderActionDetail = new SaleOrderActionDetail();
		saleOrderActionDetail.setSaleOrderId(saleOrder.getSaleOrderId());
		saleOrderActionDetail.setActionTime(acttime);
		saleOrderActionDetail.setOperId(operId);
		saleOrderActionDetail.setInitialStatus(saleOrder.getOrderStatus());
		saleOrderActionDetail
				.setEndStatus(SaleOrder.SALEORDER_ORDERSTATUS_FREEZE);
		saleOrderActionDetail
				.setActionType(SaleOrderActionDetail.ACTIONTYPE_FREEZE);
		saleOrderActionDetail.setRemark(userRemark);
		saleOrderActionDetailDaoImpl
				.insertSaleOrderActionDetail(saleOrderActionDetail);

		// 修正销售单状态
		saleOrder.setOrderStatus(SaleOrder.SALEORDER_ORDERSTATUS_FREEZE);
		saleOrderDaoImpl.updateSaleOrder(saleOrder);
		// 日志记录
		sysOperLogDaoImpl.insertSysOperLogInfo(webInput,
				SysOperLog.operType_Edit, "冻结已激活销售单", "SaleOrderId: "
						+ saleOrder.getSaleOrderId());
	}

	/**
	 * 解冻结已激活销售单
	 * 
	 * @param saleOrderId
	 *            销售单ID
	 * @param operId
	 *            操作员ID
	 * @param remark
	 *            解冻结原因
	 */
	public void unFreezeSaleOrder(PCPSWebInput webInput,
			BigInteger saleOrderId, BigInteger operId, String userRemark)
			throws PCPSApplicationException {

		// 参数检查
		SaleOrder saleOrder = checkFreezeSaleOrderArgs(saleOrderId, operId,
				userRemark);

		// 检查销售单状态 -- 必须处于冻结状态
		if (!PCPSUtil.compareObject(saleOrder.getOrderStatus(),
				SaleOrder.SALEORDER_ORDERSTATUS_FREEZE))
			throw new CardTranApplicationException(
					CardTranApplicationException.ERRCODE_CATEGORY_APPLICATION,
					"", "销售单状态不允许!");

		// 取当前时间
		Date acttime = pcpsCommonDaoImpl.getDatabaseSysTime();

		// 登记销售单状态转移明细
		SaleOrderActionDetail saleOrderActionDetail = new SaleOrderActionDetail();
		saleOrderActionDetail.setSaleOrderId(saleOrder.getSaleOrderId());
		saleOrderActionDetail.setActionTime(acttime);
		saleOrderActionDetail.setOperId(operId);
		saleOrderActionDetail.setInitialStatus(saleOrder.getOrderStatus());
		saleOrderActionDetail
				.setEndStatus(SaleOrder.SALEORDER_ORDERSTATUS_UNDOFREEZE);
		saleOrderActionDetail
				.setActionType(SaleOrderActionDetail.ACTIONTYPE_UNDOFREEZE);
		saleOrderActionDetail.setRemark(userRemark);
		saleOrderActionDetailDaoImpl
				.insertSaleOrderActionDetail(saleOrderActionDetail);

		// 修正销售单状态
		saleOrder.setOrderStatus(SaleOrder.SALEORDER_ORDERSTATUS_UNDOFREEZE);
		saleOrderDaoImpl.updateSaleOrder(saleOrder);
		// 日志记录
		sysOperLogDaoImpl.insertSysOperLogInfo(webInput,
				SysOperLog.operType_Edit, "解冻结激活销售单", "SaleOrderId: "
						+ saleOrder.getSaleOrderId());
	}
}